/*
 * Copyright (C) 2018 Logos Technology Ltd.
 */

package com.logos.common.source.network;

import android.net.ParseException;

import com.logos.common.source.network.entity.ErrorNetEntity;
import com.logos.tool.JsonParseUtil;
import com.logos.tool.string.StringUtil;
import com.google.gson.JsonParseException;

import org.json.JSONException;

import java.net.ConnectException;
import java.net.NoRouteToHostException;
import java.net.UnknownHostException;

import okhttp3.ResponseBody;
import retrofit2.HttpException;

/**
 * @author Young Ken
 */

public class ExceptionHandle {
    private static final int UNAUTHORIZED = 401;
    private static final int FORBIDDEN = 403;
    private static final int NOT_FOUND = 404;
    private static final int REQUEST_TIMEOUT = 408;
    private static final int INTERNAL_SERVER_ERROR = 500;
    private static final int BAD_GATEWAY = 502;
    private static final int SERVICE_UNAVAILABLE = 503;
    private static final int GATEWAY_TIMEOUT = 504;

    /**
     * 解析错误
     *
     * @param throwable Throwable
     * @return ResponseThrowable
     */
    public static ResponseThrowable handleException(Throwable throwable) {
        ResponseThrowable responseThrowable;
        if (throwable instanceof BaseThrowable) {
            BaseThrowable httpException = (BaseThrowable) throwable;
            responseThrowable = new ResponseThrowable(throwable, httpException.getCode());
            responseThrowable.code = httpException.getCode();
            responseThrowable.message = httpException.getMessage();
            return responseThrowable;

        } else if (throwable instanceof HttpException) {
            HttpException httpException = (HttpException) throwable;
            responseThrowable = new ResponseThrowable(throwable, Error.HTTP_ERROR);
            responseThrowable.code = httpException.code();
            if (httpException.code() / 100 == 4) {
                if (NOT_FOUND == httpException.code()) {
                    responseThrowable.message = "服务器端数据不存在";
                    return responseThrowable;
                }
                ResponseBody errorBody = httpException.response().errorBody();
                if (errorBody != null) {
                    try {
                        String jsonString = new String(errorBody.bytes());
                        if (StringUtil.isEmpty(jsonString)) {
                            responseThrowable.message = "未知错误";
                        } else {
                            ErrorNetEntity failedNetEntity = JsonParseUtil.jsonToMode(jsonString,
                                    ErrorNetEntity.class);
                            responseThrowable.message = failedNetEntity.getError().getMessage();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                return responseThrowable;
            }
            switch (httpException.code()) {
                case GATEWAY_TIMEOUT:
                case INTERNAL_SERVER_ERROR:
                case BAD_GATEWAY:
                case SERVICE_UNAVAILABLE:

                default:
                    responseThrowable.message = "网络错误";
                    break;
            }
            return responseThrowable;
        } else if (throwable instanceof ServerException) {
            ServerException resultException = (ServerException) throwable;
            responseThrowable = new ResponseThrowable(resultException, resultException.code);
            responseThrowable.message = resultException.message;
            return responseThrowable;
        } else if (throwable instanceof JsonParseException
                || throwable instanceof JSONException
                || throwable instanceof ParseException) {
            responseThrowable = new ResponseThrowable(throwable, Error.PARSE_ERROR);
            responseThrowable.message = "解析错误";
            return responseThrowable;
        } else if (throwable instanceof ConnectException) {
            responseThrowable = new ResponseThrowable(throwable, Error.NETWORD_ERROR);
            responseThrowable.message = "连接失败";
            return responseThrowable;
        } else if (throwable instanceof javax.net.ssl.SSLHandshakeException) {
            responseThrowable = new ResponseThrowable(throwable, Error.SSL_ERROR);
            responseThrowable.message = "证书验证失败";
            return responseThrowable;
        } else if (throwable instanceof NoRouteToHostException) {
            responseThrowable = new ResponseThrowable(throwable, Error.HOST_ERROR);
            responseThrowable.message = "网络错误，请重启wifi或者重启手机";
            return responseThrowable;
        } else if (throwable instanceof UnknownHostException) {
            responseThrowable = new ResponseThrowable(throwable, Error.HOST_ERROR);
            responseThrowable.message = "服务器异常，请稍后重试";
        } else if (throwable instanceof NullPointerException) {
            responseThrowable = new ResponseThrowable(throwable, Error.PARSE_ERROR);
            responseThrowable.message = "后台数据解析错误";
        } else {
            responseThrowable = new ResponseThrowable(throwable, Error.UNKNOWN);
            responseThrowable.message = "未知错误";
            return responseThrowable;
        }
        return responseThrowable;
    }

    /**
     * 约定异常
     */
    public class Error {
        /**
         * 未知错误
         */
        public static final int UNKNOWN = 1000;
        /**
         * 解析错误
         */
        public static final int PARSE_ERROR = 1001;
        /**
         * 网络错误
         */
        public static final int NETWORD_ERROR = 1002;
        /**
         * 协议出错
         */
        public static final int HTTP_ERROR = 1003;

        /**
         * 证书出错
         */
        public static final int SSL_ERROR = 1005;

        /**
         * host error
         */
        public static final int HOST_ERROR = 1006;

        /**
         * host error
         */
        public static final int NOT_NET_WORK = 1007;

        /**
         * 找不基类
         */
        public static final int NOT_FONUD_BASE_CLASS = 2001;
    }

    public static class ResponseThrowable extends Exception {
        public int code;
        public String message;

        public ResponseThrowable(Throwable throwable, int code) {
            super(throwable);
            this.code = code;
        }
    }

    public class ServerException extends RuntimeException {
        public int code;
        public String message;
    }
}
